//所有权
fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone();
    println!("s1 = {}, s2 = {}", s1, s2);

    let t1 = String::from("hello");
    let t2 = t1; 
    println!("{}, world!", t2); // 错误！t1 已经失效

    let s = String::from("hello");
    // s 被声明有效

    takes_ownership(s);
    // s 的值被当作参数传入函数
    // 所以可以当作 s 已经被移动，从这里开始已经无效

    let x = 5;
    // x 被声明有效

    makes_copy(x);
    // x 的值被当作参数传入函数
    // 但 x 是基本类型，依然有效
    // 在这里依然可以使用 x 却不能使用 s

   
    let v1 = gives_ownership();
    // gives_ownership 移动它的返回值到 v1

    let v2 = String::from("hello");
    // v2 被声明有效

    let v3 = takes_and_gives_back(v2);
    // v2 被当作参数移动, v3 获得返回值所有权
	

    let p1 = String::from("hello rust");
    let p2 = &p1;
    println!("p1 is {}, p2 is {}", p1, p2);

    
    let ss1 = String::from("hello");
    let len = calculate_length(&ss1);
    println!("The length of '{}' is {}.", ss1, len);

    
    let g1 = String::from("hello");
    let mut g2 = &g1;
    let g3 = g1;
    println!("{}", g3);
    g2 = &g3; // 重新从 g3 租借所有权


    let x1 = String::from("run");
    let x2 = &x1;
    println!("{}", x2);
    //x2.push_str("oob"); // 错误，禁止修改租借的值
    println!("{}", x2);

    
    let mut u1 = String::from("run");
    // u1 是可变的

    let u2 = &mut u1;
    // u2 是可变的引用

    u2.push_str("oob");
    println!("{}", u2);


    let mut r = String::from("hello");
    let r1 = &mut r;
    let r2 = &mut r;
    println!("{}, {}", r1, r2);

    
    let reference_to_nothing = dangle();


} // 函数结束, x 无效, 然后是 s. 但 s 已被移动, 所以不用被释放  // v3 无效被释放, v2 被移动, v1 无效被释放.


fn takes_ownership(some_string: String) {
    // 一个 String 参数 some_string 传入，有效
    println!("{}", some_string);
} // 函数结束, 参数 some_string 在这里释放

fn makes_copy(some_integer: i32) {
    // 一个 i32 参数 some_integer 传入，有效
    println!("{}", some_integer);
} // 函数结束, 参数 some_string 是基本类型, 无需释放     


fn gives_ownership() -> String {
    let some_string = String::from("hello");
    // some_string 被声明有效

    return some_string;
    // some_string 被当作返回值移动出函数
}

fn takes_and_gives_back(a_string: String) -> String { 
    // a_string 被声明有效

    a_string  // a_string 被当作返回值移出函数
}

fn calculate_length(s: &String) -> usize {
    s.len()
}


fn dangle() -> &String {
    let s = String::from("hello");

    &s
}



























